﻿using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Devonline.Core;

namespace Devonline.Identity
{
    public interface IResourceStore<TResource, TKey> : IIdentityStore<TResource, TKey> where TResource : Resource<TKey> where TKey : IEquatable<TKey>, IConvertible
    {
        /// <summary>
        /// Finds and returns parent resource, if any, who has the specified <paramref name="id"/>.
        /// </summary>
        /// <param name="id">The resource id to search for.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
        /// <returns>
        /// The <see cref="Task"/> that represents the asynchronous operation, containing the resource matching the specified <paramref name="resourceId"/> if it exists.
        /// </returns>
        Task<TResource> GetParentResourceAsync(TKey id, CancellationToken cancellationToken = default);

        /// <summary>
        /// Finds and returns children resource, if any, who has the specified <paramref name="id"/>.
        /// </summary>
        /// <param name="id">The resource id to search for.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
        /// <returns>
        /// The <see cref="Task"/> that represents the asynchronous operation, containing the resource matching the specified <paramref name="resourceId"/> if it exists.
        /// </returns>
        Task<IList<TResource>> GetChildrenResourcesAsync(TKey id, CancellationToken cancellationToken = default);

        /// <summary>
        /// Finds and returns a resource, if any, who has the specified resource owner.
        /// </summary>
        /// <param name="ownerId">The resource owner to search for.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
        /// <returns>
        /// The <see cref="Task"/> that represents the asynchronous operation, containing the resource matching the specified <paramref name="name"/> if it exists.
        /// </returns>
        Task<IList<TResource>> GetByOwnerAsync(TKey ownerId, CancellationToken cancellationToken = default);

        /// <summary>
        /// Finds and returns resources whose user has been authorized
        /// </summary>
        /// <param name="userId">user id</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IList<TResource>> GetUserAuthorizedResourcesAsync(TKey userId, CancellationToken cancellationToken);

        /// <summary>
        /// change the resource owner
        /// </summary>
        /// <param name="resource">The resource id to change for.</param>
        /// <param name="ownerId">The owner id to change for.</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task SetOwner(TResource resource, TKey ownerId, CancellationToken cancellationToken = default);

        /// <summary>
        /// change the resource parentId
        /// </summary>
        /// <param name="resource">The resource id to change for.</param>
        /// <param name="parentId">The parent id to change for.</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task SetParent(TResource resource, TKey parentId, CancellationToken cancellationToken = default);

        /// <summary>
        /// change the resource ResourceType
        /// </summary>
        /// <param name="resource">The resource id to change for.</param>
        /// <param name="resourceType">The resourceType to change for.</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task SetResourceType(TResource resource, ResourceType resourceType, CancellationToken cancellationToken = default);

        /// <summary>
        /// change the resource content
        /// </summary>
        /// <param name="resource">The resource id to change for.</param>
        /// <param name="content">The path to change for.</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task SetContent(TResource resource, string content, CancellationToken cancellationToken = default);

        /// <summary>
        /// change the resource ProtectionLevel
        /// </summary>
        /// <param name="resource">The resource id to change for.</param>
        /// <param name="accessLevel">The AccessLevel to change for.</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task SetAccessLevel(TResource resource, AccessLevel accessLevel, CancellationToken cancellationToken = default);
    }
}
